using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Multiplicity.Reflection {

    public abstract class StorageHeap<T> {

        readonly StorageHeapHeader head;
        readonly Module module; 
        readonly long bufferOffset;
        readonly byte[] buffer;

        readonly Dictionary<uint, T> items = new Dictionary<uint, T>();

        /// <param name="metadataOffset">file offset of the storage root</param>
        protected StorageHeap(Module mod, StorageHeapHeader head, long metadataOffset) {
            this.head = head;
            this.module = mod;
            this.buffer = mod.Image;
            this.bufferOffset = metadataOffset + head.Offset;
        }

        public T this[uint index] {
            get {
                Throw.ArgumentOutOfRangeExceptionIf(!IsValidIndex(index));

                if (!items.ContainsKey(index)) {
                    items[index] = ReadItem(index);
                }

                return items[index];
            }
        }

        protected abstract bool IsValidIndex(uint index);
        protected abstract T ReadItem(uint index);

        protected Module Module {
            get { return module; }
        }

        protected StorageHeapHeader Header {
            get { return head; }
        }

        protected byte[] Buffer {
            get { return buffer; }
        }

        protected long BufferOffset {
            get { return bufferOffset; }
        }
    }
}
